package shark.flow.identity.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.idm.api.User;
import org.flowable.idm.engine.impl.UserQueryImpl;
import org.flowable.idm.engine.impl.persistence.entity.UserEntity;
import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import shark.user.spi.entity.SysUser;
import shark.user.spi.mapper.SysUserMapper;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class SharkUserQueryImpl extends UserQueryImpl implements ApplicationContextAware {

    private SysUserMapper sysUserMapper;

    public SharkUserQueryImpl() {}

    public SharkUserQueryImpl(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

    public SharkUserQueryImpl(CommandContext commandContext) {
        super(commandContext);
    }

    @Override
    public long executeCount(CommandContext commandContext) {
        return executeQuery().size();
    }

    @Override
    public List<User> executeList(CommandContext commandContext) {
        return executeQuery();
    }

    protected List<User> executeQuery() {
        if (getId() != null) {
            List<User> result = new ArrayList<>();
            UserEntity user = findById(getId());
            if (user != null) {
                result.add(user);
            }
            return result;

        } else if (getIdIgnoreCase() != null) {
            List<User> result = new ArrayList<>();
            UserEntity user = findById(getIdIgnoreCase());
            if (user != null) {
                result.add(user);
            }
            return result;

        } else if (getFullNameLike() != null) {
            return executeNameQuery(getFullNameLike());

        } else if (getFullNameLikeIgnoreCase() != null) {
            return executeNameQuery(getFullNameLikeIgnoreCase());

        } else {
            return executeAllUserQuery();
        }
    }

    protected UserEntity findById(final String userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (sysUser == null) {
            log.error("Could not find user {}", userId);
            return null;
        }
        UserEntityImpl userEntity = new UserEntityImpl();
        userEntity.setId(sysUser.getId());
        userEntity.setPassword(sysUser.getPassword());
        userEntity.setLastName(sysUser.getRealname());
        userEntity.setFirstName(sysUser.getRealname());
        userEntity.setDisplayName(sysUser.getUsername());
        userEntity.setEmail(sysUser.getEmail());
        return userEntity;
    }

    protected List<User> executeNameQuery(String name) {
        String fullName = name.replaceAll("%", "");
        List<User> users = new ArrayList<>();
        List<SysUser> list = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, fullName));
        for (SysUser sysUser : list) {
            UserEntityImpl userEntity = new UserEntityImpl();
            userEntity.setId(sysUser.getId());
            userEntity.setPassword(sysUser.getPassword());
            userEntity.setLastName(sysUser.getRealname());
            userEntity.setFirstName(sysUser.getRealname());
            userEntity.setDisplayName(sysUser.getUsername());
            userEntity.setEmail(sysUser.getEmail());
            users.add(userEntity);
        }
        return users;
    }

    protected List<User> executeAllUserQuery() {
        List<User> users = new ArrayList<>();
        List<SysUser> list = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>());
        for (SysUser sysUser : list) {
            UserEntityImpl userEntity = new UserEntityImpl();
            userEntity.setId(sysUser.getId());
            userEntity.setPassword(sysUser.getPassword());
            userEntity.setLastName(sysUser.getRealname());
            userEntity.setFirstName(sysUser.getRealname());
            userEntity.setDisplayName(sysUser.getUsername());
            userEntity.setEmail(sysUser.getEmail());
            users.add(userEntity);
        }
        return users;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        sysUserMapper = applicationContext.getBean(SysUserMapper.class);
    }
}
